import avueOptionTools from "@/config/avueOptionTools";
import {deepClone} from "utils/util";

const commonSelect = {
    toAvue: commonSelectToAvue,
    toDesign: commonSelectToDesign,
}

function commonSelectToAvue(option, col, index) {
    switch (col.dicOption) {
        case  'static':
            delete col.dicUrl
            delete col.dicMethod
            delete col.dicQuery
            delete col.dicQueryConfig
            break
        case 'remote':
            delete col.dicData
            let dicQueryConfig = col.dicQueryConfig || []
            delete col.dicQueryConfig
            if (dicQueryConfig.length < 1) {
                break
            }
            const query = {}
            col.dicQueryConfig.forEach(q => {
                if (q.key && q.value) query[q.key] = q.value
            })
            col.dicQuery = query
            break
        case "sysDict":
            col.dicUrl = avueOptionTools.dictUrl;
            col.dicMethod = avueOptionTools.dicMethod
            col.props = avueOptionTools.dicProps
            break
    }
    delete col.dicOption
    return col;
}

function commonSelectToDesign(option, col, index) {
    if (col.dicData) {
        col.dicOption = 'static'
        return col
    } else if (col.dicUrl && col.dicUrl.indexOf(avueOptionTools.dictUrl) > -1) {
        col.dicQuery = col.dicQuery || {}
        col.dicOption = "sysDict"
        col.props = avueOptionTools.dicProps
        return col;
    }
    col.dicOption = "remote"
    let dicQuery = col.dicQuery || {}
    if (typeof dicQuery != 'object') {
        return col;
    }
    const dicQueryConfig = []
    for (let key in dicQuery) {
        let config = {}
        config.key = key;
        config.value = dicQuery[key]
        config.$cellEdit = true
        dicQueryConfig.push(config)
    }
    col.dicQueryConfig = dicQueryConfig
    return col;
}

const componentsMapping = {
    dynamic: {
        toAvue(option, col, index) {
            col.children = col.children || {}
            col.children.column = col.children.column || [];
            col.children.column.forEach(item => {
                delete item.subfield
            })
            col.children = designOptionToAvueOption(col.children);
            return col

        },
        toDesign(option, col, index) {
            col.children = col.children || {}
            col.children.column = col.children.column || []
            for (let i = 0; i < col.children.column.length; i++) {
                col.children.column[i].subfield = true;
            }
            col.children = avueOptionToDesignOption(col.children);
            return col;
        },
    },
    group: {
        toAvue(option, col, index) {
            if (!option.group) option.group = []
            const group = {}
            group.label = col.label;
            group.icon = col.icon;
            group.prop = col.prop;
            group.arrow = col.arrow;
            group.collapse = col.collapse;
            group.display = col.display;
            let res = designOptionToAvueOption(col.children)
            group.column = res.column
            option.group.push(group)
        },
        toDesign(option, col, index) {

            const group = {}
            group.type = 'group';
            group.label = col.label;
            group.icon = col.icon;
            group.prop = col.prop;
            group.arrow = col.arrow;
            group.collapse = col.collapse;
            group.display = col.display;
            group.children = designOptionToAvueOption(col)
            return group;
        },
    },
    upload: {
        toAvue(option, col, index) {
            delete col.headers
            let headersConfig = col.headersConfig || []
            delete col.headersConfig
            if (headersConfig.length > 0) {
                const headers = {}
                col.headersConfig.forEach(h => {
                    if (h.key && h.value) headers[h.key] = h.value
                })
                col.headers = headers
            }
            let dataConfig = col.dataConfig || []
            delete col.dataConfig
            delete col.data
            if (dataConfig.length > 0) {
                const data = {}
                col.dataConfig.forEach(h => {
                    if (h.key && h.value) data[h.key] = h.value
                })
                col.data = data
            }
            return col
        },
        toDesign(option, col, index) {
            let headers = col.headers || {}
            col.headersConfig = []
            for (let key in headers) {
                let config = {}
                config.key = key;
                config.value = headers[key]
                config.$cellEdit = true
                col.headersConfig.push(config)
            }
            let data = col.data || {}
            col.dataConfig = []
            for (let key in data) {
                let config = {}
                config.key = key;
                config.value = data[key]
                config.$cellEdit = true
                col.dataConfig.push(config)
            }
            return col;

        },
    },
    checkbox: commonSelect,
    radio: commonSelect,
    tree: commonSelect,
    cascader: commonSelect,
    select: commonSelect
}


/**
 * 列信息转avue列信息
 * @param option 表单配置对象
 * @param col  当前字段配置项
 * @param index 下标
 * @returns {*|null}
 */
function columnToAvue(option, col, index) {
    let colType = col.component || col.type
    let mapping = componentsMapping[colType]
    if (!mapping) {
        return col;
    }
    let toAvue = mapping.toAvue
    if (!toAvue) {
        return col;
    }
    if (!toAvue instanceof Function) {
        console.error(mapping)
        throw new Error("mapping type  " + colType + "  toAvue not is function")
    }
    let result = toAvue(option, col, index)
    if (!result) {
        return null;
    }
    return result;
}

/**
 * 列信息转design列信息
 * @param option 表单配置对象
 * @param col  当前字段配置项
 * @param index 下标
 * @returns {*|null}
 */
function columnToDesign(option, col, index) {
    let colType = col.component || col.type
    let mapping = componentsMapping[colType]
    if (!mapping) {
        return col;
    }
    let toDesign = mapping.toDesign
    if (!toDesign) {
        return col;
    }
    if (!toDesign instanceof Function) {
        console.error(mapping)
        throw new Error("mapping type  " + colType + "  toDesign not is function")
    }
    let result = toDesign(option, col, index)
    if (!result) {
        return null;
    }
    return result;
}

/**
 * 设置配置对象转avue配置对象
 * @param designOption
 * @returns {*}
 */
function designOptionToAvueOption(designOption) {
    const data = deepClone(designOption)
    let column = []
    for (let i = 0; i < data.column.length; i++) {
        let avueCol = columnToAvue(data, data.column[i], i)
        if (!avueCol) {
            continue
        }
        if (avueCol.click) {
            avueCol.click = eval(avueCol.click)
        } else {
            delete avueCol.click
        }
        if (avueCol.focus) {
            avueCol.focus = eval(avueCol.focus)
        } else {
            delete avueCol.focus
        }
        if (avueCol.blur) {
            avueCol.blur = eval(avueCol.blur)
        } else {
            delete avueCol.blur
        }
        column.push(avueCol)
    }
    data.column = column
    return data;
}

/**
 * avue配置对象转设计配置对象
 * @param avueOption
 * @returns {*}
 */
function avueOptionToDesignOption(avueOption) {
    if (typeof avueOption == 'string') {
        avueOption = eval('(' + avueOption + ')')
    }
    const data = deepClone(avueOption)
    let column = data.column || []
    let designColumn = []
    for (let i = 0; i < column.length; i++) {
        let col = column[i];
        let designCol = columnToDesign(data, col, i)
        if (!designCol) {
            continue
        }
        designColumn.push(designCol);
    }
    let groups = data.group || []
    for (let i = 0; i < groups.length; i++) {
        let designCol = componentsMapping.group.toDesign(data, groups[i], i)
        if (!designCol) {
            continue
        }
        designColumn.push(designCol);
    }
    delete data.group
    data.column = designColumn;
    return data;
}

const designTools = {
    designOptionToAvueOption,
    avueOptionToDesignOption
}
export default designTools
